package model

import (
	"app/common/customtype"
	"app/pkg/db"
	"fmt"

	"github.com/shopspring/decimal"
	"gorm.io/gorm"
)

type CommonStruct struct {
	Id         int64                `gorm:"column:id" json:"id,omitempty"`
	CreateTime customtype.LocalTime `gorm:"column:create_time" json:"createTime"`
	UpdateTime customtype.LocalTime `gorm:"column:update_time" json:"updateTime"`
}

type SingleFileResponse struct {
	Path     string `json:"path"`
	Size     int64  `json:"size"`
	Url      string `json:"url"`
	ThumbUrl string `json:"thumbUrl"`
}

// 返回秒数
func GetBonusRedisExpireTime() int {
	return 24 * 60 * 60
}

// 插入记录
func Insert[T any](table string, obj T, omitColumn []string) (res T, err error) {
	omitSlice := []string{"create_time", "update_time"}
	omitSlice = append(omitSlice, omitColumn...)
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	err = conn.Table(table).Omit(omitSlice...).Create(&obj).Error
	if err == nil {
		res = obj
	}
	return
}

// 事务插入
func InsertByTrans[T any](conn *gorm.DB, req *T, omitColumn []string) (err error) {
	omitSlice := []string{"create_time", "update_time"}
	omitSlice = append(omitSlice, omitColumn...)
	err = conn.Omit(omitSlice...).Create(req).Error
	return
}

// 事务Incre
func IncreByTrans(conn *gorm.DB, tableName string, id int64, inc decimal.Decimal, column string) (err error) {
	sql := fmt.Sprintf("update %s set %s = %s+? where id=%d", tableName, column, column, id)
	err = conn.Exec(sql, inc).Error
	return
}

func Incre(tableName string, id int64, inc decimal.Decimal, column string) (err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	sql := fmt.Sprintf("update %s set %s = %s+? where id=%d", tableName, column, column, id)
	err = conn.Exec(sql, inc).Error
	return
}

func Update(table string, where, data map[string]interface{}) (err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	err = conn.Table(table).Where(where).Updates(data).Error
	return
}

func UpdateByTrans(conn *gorm.DB, table string, where, data map[string]interface{}) (err error) {
	err = conn.Table(table).Where(where).Updates(data).Error
	return
}

func Delete[T any](where map[string]interface{}) (err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	var obj T
	err = conn.Delete(obj, where).Error
	return
}

func FindOne[T any](where interface{}, args ...interface{}) (reply T, err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	var obj T
	err = conn.Model(&obj).Where(where, args...).Take(&reply).Error
	return
}

func FindOneByTrans[T any](tx *gorm.DB, where map[string]interface{}) (reply T, err error) {
	var obj T
	err = tx.Model(&obj).Where(where).Take(&reply).Error
	return
}

func Find[T any](where map[string]interface{}) (reply []T, err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	var obj T
	err = conn.Model(&obj).Where(where).Find(&reply).Error
	return
}

func FindSystem[T any](query interface{}, args ...interface{}) (reply []T, err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	var obj T
	err = conn.Model(&obj).Where(query, args...).Order("id DESC").Find(&reply).Error
	return
}

func FindSystemSort[T any](sort string, query interface{}, args ...interface{}) (reply []T, err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	var obj T
	err = conn.Model(&obj).Where(query, args...).Order(sort).Find(&reply).Error
	return
}

func Save[T any](obj *T) error {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return err
	}
	return conn.Omit("create_time", "update_time").Save(obj).Error
}

func SaveByTrans[T any](tx *gorm.DB, obj *T) error {
	return tx.Omit("create_time", "update_time").Save(obj).Error
}

// 分页器
func PaginateScope(page int, limit int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page == 0 {
			page = 1
		}
		switch {
		case limit > 100:
			limit = 100
		case limit <= 0:
			limit = 10
		}
		offset := (page - 1) * limit
		return db.Offset(offset).Limit(limit)
	}
}

func UserNormalScope(column string) func(db *gorm.DB) *gorm.DB {
	if column == "" {
		column = "state"
	}
	return func(db *gorm.DB) *gorm.DB {
		return db.Where(fmt.Sprintf("%s = ?", column), USER_STATE_NORMAL)
	}
}
